﻿using FluentAssertions;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using NewRetail.Application.Components.Goods;
using NewRetail.Application.Components.Goods.Entity;
using NewRetail.Application.Components.Platform.Entity;
using NewRetail.Application.Components.Warehouse;
using NewRetail.Application.Components.Warehouse.Entity;
using NewRetail.Application.Core;
using NewRetail.Application.Utility;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Domain.Repositories;

namespace NewRetail.Api.Controllers
{
    [NewRetailRoute("warehouse")]
    public class WarehouseController : BaseController<Warehouse, WarehousePagingRequestDto>
    {
        private readonly IWarehouseService warehouseService;
        private readonly ILogger _logger;

        public WarehouseController(IWarehouseService warehouseService, ILogger<WarehouseController> logger)
        {
            this.warehouseService = warehouseService;
            _logger = logger;
        }

        protected override async Task<IQueryable<Warehouse>> FilterQueryPaging(DbContext db, IQueryable<Warehouse> query, WarehousePagingRequestDto dto)
        {
            if (!string.IsNullOrWhiteSpace(dto.name))
            {
                query = query.Where(x => x.warehouseName.Contains(dto.name));
            }
            if (!string.IsNullOrWhiteSpace(dto.no))
            {
                query = query.Where(x => x.No == dto.no);
            }
            await Task.CompletedTask;
            return query;
        }

        protected override async Task<Warehouse> BeforeInsert(Warehouse data)
        {
            if (await this.Repo.AnyAsync(x => x.No == data.No))
            {
                throw new UserFriendlyException("门店号存在");
            }
            return await base.BeforeInsert(data);
        }

        protected override async Task<Warehouse> BeforeInsertDataInitial(Warehouse data)
        {
            if (string.IsNullOrWhiteSpace(data.No))
            {
                data.No = await this.NoGeneratorService.GenerateGeneralNoAsync("WH");
            }
            return await base.BeforeInsertDataInitial(data);
        }

        protected override Task<Warehouse> BeforeUpdate(Warehouse entity, Warehouse data)
        {
            entity.warehouseName = data.warehouseName;
            entity.remark = data.remark;
            entity.isEnable = data.isEnable;
            return base.BeforeUpdate(entity, data);
        }

        [HttpPost("get-warehouse-config")]
        public async Task<ResponseEntity<WarehouseConfiguration>> GetWarehouseConfiguration([FromBody] NoDto dto)
        {
            dto.Should().NotBeNull();
            dto.no.Should().NotBeNullOrEmpty();
            var warehouse = await this.Repo.FirstOrDefaultAsync(x => x.No == dto.no);
            if (warehouse == null)
            {
                throw new UserFriendlyException("门店不存在");
            }

            var data = await this.warehouseService.GetWarehouseConfiguration(warehouse.Id);

            return new ResponseEntity<WarehouseConfiguration>().SetData(data);
        }

        [HttpPost("get-warehouse-goods")]
        public async Task<ResponseEntity<WarehouseGoods[]>> GetWarehouseGoods([FromBody] GetWarehouseGoodsDto dto)
        {
            dto.Should().NotBeNull();
            dto.WarehouseNo.Should().NotBeNullOrEmpty();
            dto.Page ??= 1;
            (dto.Page >= 1).Should().BeTrue();

            var db = await this.Repo.GetDbContextAsync();

            var warehouse = await db.Set<Warehouse>().IgnoreQueryFilters().FirstOrDefaultAsync(x => x.No == dto.WarehouseNo);
            if (warehouse == null)
            {
                throw new UserFriendlyException("门店不存在");
            }

            var query = from map in db.Set<WarehouseGoods>().IgnoreQueryFilters().AsNoTracking().Where(x => x.warehouseID == warehouse.Id)
                        join goods in db.Set<GoodsInfo>().IgnoreQueryFilters().AsNoTracking() on map.goodsID equals goods.Id into os
                        from good in os.DefaultIfEmpty()
                        select new { map, good };
            ////移到上面防止出现重复
            //query = query.OrderBy(x => x.map.updateTime);
            query = query.WhereIf(dto.UpdateTime != null,
                x =>
                x.map.updateTime >= dto.UpdateTime.Value ||
                x.good.updateTime >= dto.UpdateTime.Value || x.map.addTime >= dto.UpdateTime.Value || x.good.addTime >= dto.UpdateTime.Value);

            query = query.OrderBy(x => x.map.updateTime).ThenBy(x => x.good.updateTime)
                .ThenBy(x => x.map.addTime).ThenBy(x => x.good.addTime).Page(dto.Page.Value, pageSize: 100);
            ////query = query.OrderBy(x => x.map.updateTime).Page(dto.Page.Value, pageSize: 100);
            //query = query.Page(dto.Page.Value, pageSize: 300);

            var data = await query.ToArrayAsync();

            var res = data.Select(x =>
            {
                x.map.GoodsInfo = x.good;
                return x.map;
            }).ToArray();

            return new ResponseEntity<WarehouseGoods[]>().SetData(res);
        }

        [HttpPost("get-warehouse-members")]
        public async Task<ResponseEntity<PosMember[]>> GetWarehouseMembers([FromBody] GetWarehouseMemberDto dto)
        {
            _logger.LogInformation(message: $"get-warehouse-members传入参数：{UtilsHelper.SerializeObject(dto)}");
            dto.Should().NotBeNull();
            dto.Page ??= 1;
            (dto.Page >= 1).Should().BeTrue();

            var db = await this.Repo.GetDbContextAsync();

            var query = db.Set<PosMember>().IgnoreQueryFilters().AsNoTracking();

            if (!string.IsNullOrWhiteSpace(dto.WarehouseNo))
            {
                var warehouse = await db.Set<Warehouse>().IgnoreQueryFilters().FirstOrDefaultAsync(x => x.No == dto.WarehouseNo);
                if (warehouse == null)
                {
                    throw new UserFriendlyException("门店不存在");
                }
                query = query.Where(x => x.sourceWarehouseID == warehouse.Id);
            }

            if (dto.UpdateTime != null)
            {
                query = query.Where(x => x.updateTime >= dto.UpdateTime.Value);
            }

            query = query.OrderBy(x => x.updateTime).Page(dto.Page.Value, pageSize: 100);

            var data = await query.ToArrayAsync();

            return new ResponseEntity<PosMember[]>().SetData(data);
        }
    }
}
